﻿using Castle.DynamicProxy;
using CNKI.TPI.Web.Admin.IBLL;
using CNKI.TPI.Web.Admin.IDAO;
using CNKI.TPI.Web.Admin.Model;
using CNKI.TPI.Web.Base;
using CNKI.TPI.Web.Search.IDAO;
using CNKI.TPI.Web.Search.Model;
using KNet.Data.Entity;
using KNet.Data.KBaseClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace CNKI.TPI.Web.Admin.BLL
{
    public class MultiDBPublishService : BaseService, IMultiDBPublishService
    {
        private IMultiDBPublishDAO multiDbDao = null;
        private IUserDBDAO userDBDAO = null;
        private ICategoryDAO categoryDAO = null;
        private ISingleDBPublishDAO singDbDao;
        IHomeConfigDAO homeConfigDao = null;
        public MultiDBPublishService(IMultiDBPublishDAO multiDbDao, IUserDBDAO userDBDAO, ICategoryDAO categoryDAO, ISingleDBPublishDAO singDbDao, IHomeConfigDAO homeConfigDao)
        {
            this.homeConfigDao = this.generator.CreateInterfaceProxyWithTarget<IHomeConfigDAO>(homeConfigDao, new IInterceptor[] { new LogInterceptor() });
            this.multiDbDao = this.generator.CreateInterfaceProxyWithTarget<IMultiDBPublishDAO>(multiDbDao, new IInterceptor[] { new LogInterceptor() });
            this.userDBDAO = this.generator.CreateInterfaceProxyWithTarget<IUserDBDAO>(userDBDAO, new IInterceptor[] { new LogInterceptor() });
            this.categoryDAO = this.generator.CreateInterfaceProxyWithTarget<ICategoryDAO>(categoryDAO, new IInterceptor[] { new LogInterceptor() });
            this.singDbDao = this.generator.CreateInterfaceProxyWithTarget<ISingleDBPublishDAO>(singDbDao, new IInterceptor[] { new LogInterceptor() });
        }

        /// <summary>
        /// 保存跨库分类
        /// </summary>
        /// <returns></returns>
        public bool SavetDBClass(DBCLASS obj, string m)
        {
            bool flage = false;
            if (m == "save")
            {
                flage = multiDbDao.SaveDBClass(obj);
            }
            else
            {
                flage = multiDbDao.UpdateDBClass(obj.ClassName, obj.ClassCode);
            }
            return flage;

        }

        /// <summary>
        /// 删除跨库分类
        /// </summary>
        /// <returns></returns>
        public bool DeleteDBClass(string code)
        {
            bool flage = true;
            try
            {
                multiDbDao.DeleteDBClass(code);
                IList<string> listcode = code.Split('+');
                DeleteDBClassFromDBConfig(listcode);

            }
            catch
            {
                flage = false;
            }
            return flage;
        }


        /// <summary>
        /// 删除DBConfig里的ClassCode
        /// </summary>
        /// <param name="classCode"></param>
        private void DeleteDBClassFromDBConfig(IList<string> classCode, IList<DBCONFIG> dbConfig = null)
        {
            IList<DBCONFIG> modifedConfig = new List<DBCONFIG>();
            IList<DBCONFIG> dbconfigList = null;
            if (null == dbConfig)
            {
                dbconfigList = userDBDAO.GetUnionDB();
            }
            else
            {
                dbconfigList = dbConfig;
            }

            IList<string> classList = null;
            foreach (string item in classCode)
            {
                foreach (DBCONFIG dbconfig in dbconfigList)
                {
                    classList = dbconfig.ClassID.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                    if (classList.Contains(item))
                    {
                        classList.Remove(item);
                        dbconfig.ClassID = string.Join("|", classList);
                        if (!modifedConfig.Contains(dbconfig))
                        {
                            modifedConfig.Add(dbconfig);
                        }
                    }
                }
            }
            multiDbDao.UpdateDBClassFromDBConfig(modifedConfig);
        }

        /// <summary>
        /// 在DBConfig中添加ClassCode
        /// </summary>
        /// <param name="classCode"></param>
        private void AddDBClassToDBConfig(IList<string> classCode, IList<DBCONFIG> dbConfig = null, IList<DBCONFIG> pageInfo = null)
        {
            IList<DBCONFIG> modifedConfig = new List<DBCONFIG>();
            IList<DBCONFIG> dbconfigList = null;
            if (null == dbConfig)
            {
                dbconfigList = userDBDAO.GetUnionDB();
            }
            else
            {
                dbconfigList = dbConfig;
            }

            IList<string> classList = null;
            foreach (string item in classCode)
            {
                foreach (DBCONFIG dbconfig in dbconfigList)
                {
                    classList = dbconfig.ClassID.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).ToList();
                    if (!classList.Contains(item))
                    {
                        classList.Add(item);
                        dbconfig.ClassID = string.Join("|", classList);
                        if (!modifedConfig.Contains(dbconfig))
                        {
                            modifedConfig.Add(dbconfig);
                        }
                    }

                    DBCONFIG page = pageInfo.Where(c => c.DbID == dbconfig.DbID).ToList()[0];
                    if (page.DefaultSelected != dbconfig.DefaultSelected)
                    {
                        dbconfig.DefaultSelected = page.DefaultSelected;
                        if (!modifedConfig.Contains(dbconfig))
                        {
                            modifedConfig.Add(dbconfig);
                        }
                    }
                }
            }
            multiDbDao.UpdateDBClassFromDBConfig(modifedConfig);
        }

        /// <summary>
        /// 更新数据库的分类信息
        /// </summary>
        /// <param name="classCode"></param>
        /// <param name="configList"></param>
        /// <returns></returns>
        public bool UpdateDBConfig(string classCode, IList<DBCONFIG> configList)
        {
            bool result = false;
            try
            {
                //获得DBID列表
                IList<int> configDBIDList = configList.Select(c => c.DbID).ToList();
                //获得所有DBConfig
                IList<DBCONFIG> currentDBInfoList = userDBDAO.GetUnionDB();
                //查找所有需要删除的DBConfig
                IList<DBCONFIG> removeDBList = currentDBInfoList.Where(c => !configDBIDList.Contains(c.DbID)).ToList();
                IList<string> classCodeList = new List<string>();
                classCodeList.Add(classCode);
                //删除DBConfig中指定的classCode
                DeleteDBClassFromDBConfig(classCodeList, removeDBList);
                //查找所有需要添加的DBConfig
                IList<DBCONFIG> updateDBList = currentDBInfoList.Where(c => configDBIDList.Contains(c.DbID)).ToList();
                //添加classCode到DBConfig中
                AddDBClassToDBConfig(classCodeList, updateDBList, configList);

                //如果不相等，说明需要插入数据
                if (configList.Count != updateDBList.Count)
                {
                    IList<int> updateDBIDList = updateDBList.Select(c => c.DbID).ToList();
                    IList<DBCONFIG> addDbConfigList = configList.Where(c => !updateDBIDList.Contains(c.DbID)).ToList();
                    IList<SYS_CMS_DATABASE> dbInfoList = categoryDAO.GetDatabaseByID(addDbConfigList.Select(c => c.DbID));
                    SYS_CMS_DATABASE dbinfo = null;
                    foreach (DBCONFIG item in addDbConfigList)
                    {
                        dbinfo = dbInfoList.Where(c => c.SysID == item.DbID).ToList()[0];
                        item.CNName = dbinfo.DatabaseName;
                        item.DbCode = dbinfo.DatabaseCode;
                        item.DbDescript = dbinfo.DatabaseDescript;
                        item.ClassID = classCode;
                        item.SearchFields = "";
                        item.DbOwner = "";
                        item.DbLanguage = 0;
                        item.SortNum = dbinfo.SortSn;

                    }
                    multiDbDao.AddDBConfig(addDbConfigList);
                }
                result = true;
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        /// <summary>
        /// 根据公共字段名称，获取数据
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public IList<SYS_CMS_US_FIELD> GetUSFieldByName(string name)
        {
            IList<SYS_CMS_US_FIELD> result = null;
            try
            {
                result = multiDbDao.GetUSFiledByName(name);
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

        /// <summary>
        /// 获取所有已经发布的数据库列表
        /// </summary>
        /// <returns></returns>
        public IList<SYS_CMS_DATABASE> GetPublishDBList(bool visible = true)
        {
            return multiDbDao.GetPublishDBList(visible: visible);
        }

        /// <summary>
        /// 根据数据库ID获得对应的列表
        /// </summary>
        /// <param name="dbID"></param>
        /// <returns></returns>
        public IList<SYS_CMS_US_FIELDMAP> GetDBMapInfo(int dbID)
        {
            IList<SYS_CMS_US_FIELDMAP> result = new List<SYS_CMS_US_FIELDMAP>();
            try
            {
                IList<SYS_CMS_US_FIELDMAP> usFieldMapList = multiDbDao.GetUSFieldMap(dbID);
                if (usFieldMapList != null && usFieldMapList.Count > 0)
                {
                    IList<SYS_CMS_US_FIELD> usFieldList = multiDbDao.GetUSFieldByID(usFieldMapList.Select(c => c.USFieldID).ToList());
                    IList<SYS_CMS_DATABASE_FIELD> dbFieldList = singDbDao.GetDBFieldByID(usFieldMapList.Select(c => c.FieldID).ToList());
                    SYS_CMS_US_FIELD usField = null;
                    SYS_CMS_DATABASE_FIELD dbField = null;
                    foreach (SYS_CMS_US_FIELDMAP item in usFieldMapList)
                    {
                        usField = usFieldList.Where(c => c.SYSID == item.USFieldID).ToList()[0];
                        dbField = dbFieldList.Where(c => c.SysID == item.FieldID).ToList()[0];
                        item.USFieldName = usField.Name;
                        item.DBFieldName = dbField.Field;
                    }
                    result = usFieldMapList;
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }
        /// <summary>
        /// 获取数据库映射
        /// </summary>
        /// <param name="pageIndexNow"></param>
        /// <param name="pageSize"></param>
        /// <param name="type"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public IList<SYS_CMS_DATABASE> GetDBMappingList(int pageIndexNow, int pageSize, string type, string name, out int count)
        {
            count = 0;
            IList<SYS_CMS_DATABASE> list = singDbDao.GetDBList();
            IList<SYS_CMS_DATABASE> listpage = new List<SYS_CMS_DATABASE>();
            if (list != null && list.Count > 0)
            {
                foreach (SYS_CMS_DATABASE item in list)  //该数据库是否已经映射
                {
                    IList<SYS_CMS_US_FIELDMAP> usFieldMapList = multiDbDao.GetUSFieldMap(item.SysID);
                    if (usFieldMapList != null && usFieldMapList.Count > 0)
                    {
                        item.MappingFlag = 1;
                    }
                    else
                    {
                        item.MappingFlag = 0;
                    }
                    SYS_CMS_RESOURCE_TEMPLATE templateobj = homeConfigDao.GetTemplateByID(item.DatabaseType);//获取数据库类型
                    if (templateobj != null)
                    {
                        item.DatabaseTypeName = templateobj.RESOURCENAME;
                    }
                }
                if (type != "all")
                {
                    list = list.Where(c => c.MappingFlag == int.Parse(type)).ToList();
                }
                if (name != "")
                {
                    list = list.Where(c => c.DatabaseName.Contains(name)).ToList();
                    foreach (SYS_CMS_DATABASE item in list)
                    {
                        string redstr = "###" + name + "$$$"; //构造和drs返回值一致的标红标示
                        item.DatabaseName = item.DatabaseName.Replace(name, redstr);
                        item.DatabaseName = StringHelper.ConvertHighlightFlag(item.DatabaseName);
                    }
                }
                count = list.Count; //总记录数
                //分页，返回记录
                int startlen = (pageIndexNow - 1) * pageSize;
                int maxlen = startlen + pageSize;
                if (maxlen > count)
                {
                    maxlen = count;
                }
                for (int i = startlen; i < maxlen; i++)
                {
                    listpage.Add(list[i]);
                }

            }
            return listpage;

        }

        /// <summary>
        /// 删除SYS_CMS_US_FIELDMAP
        /// </summary>
        /// <param name="configList"></param>
        /// <returns></returns>
        public bool DeleteFIELDMAP(SYS_CMS_US_FIELDMAP fieldmap)
        {
            SYS_CMS_US_FIELDMAP fieldMap = multiDbDao.GetUSFieldMapByID(fieldmap.SysID);
            bool result = multiDbDao.DeleteFIELDMAP(fieldmap);
            if (result)
            {
                if (fieldMap != null)
                {
                    SYS_CMS_DATABASE dbInfo = categoryDAO.GetDatabaseByID(fieldMap.DBID);
                    if (dbInfo.SearchType == (int)SearchType.TPI)
                    {
                        SYS_CMS_DATABASE_FIELD dbField = singDbDao.GetDBFieldByID(new List<int>() { fieldMap.FieldID })[0];
                        if (dbField.IsSystemField != 1)
                        {
                            HS_TABLE_FIELD fieldInfo = multiDbDao.GetFieldInfo(dbInfo.DatabaseCode, dbField.Field);
                            fieldInfo.AliasName = "";
                            multiDbDao.UpdateFieldInfo(dbInfo.DatabaseCode, fieldInfo);
                        }
                    }
                }
            }
            return result;
        }
        /// <summary>
        /// 获取数据字段
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public IList<SYS_CMS_DATABASE_FIELD> GetDBFiledByDbCode(string code)
        {
            return multiDbDao.GetDBFiledByDbCode(code);
        }
        /// <summary>
        /// 获取公共映射字段
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public IList<SYS_CMS_US_FIELD> GetUSFiled()
        {
            return multiDbDao.GetUSFiled();
        }
        /// <summary>
        /// 保存映射字段
        /// </summary>
        /// <param name="dbfieldID"></param>
        /// <param name="usfield"></param>
        /// <param name="dbid"></param>
        /// <returns></returns>
        public int MappingSave(string dbfieldID, string usfieldID, string dbid, string flage, string sysid)
        {

            int m = 0;
            if (flage == "add")//新增
            {
                m = addMapping(dbfieldID, usfieldID, dbid);
            }
            else
            {
                m = updateMapping(dbfieldID, usfieldID, dbid, sysid);
            }
            if (1 == m)
            {
                SYS_CMS_DATABASE dbInfo = categoryDAO.GetDatabaseByID(int.Parse(dbid));
                if (dbInfo.SearchType == (int)SearchType.TPI)
                {
                    SYS_CMS_US_FIELD usField = multiDbDao.GetUSFieldByID(new List<int>() { int.Parse(usfieldID) })[0];
                    SYS_CMS_DATABASE_FIELD dbField = singDbDao.GetDBFieldByID(new List<int>() { int.Parse(dbfieldID) })[0];
                    if (dbField.IsSystemField != 1)
                    {
                        HS_TABLE_FIELD fieldInfo = multiDbDao.GetFieldInfo(dbInfo.DatabaseCode, dbField.Field);
                        if (!usField.Name.Equals(fieldInfo.AliasName))
                        {
                            fieldInfo.AliasName = usField.Name;
                            m = multiDbDao.UpdateFieldInfo(dbInfo.DatabaseCode, fieldInfo);
                        }
                    }

                }
            }
            return m;
        }
        /// <summary>
        /// 新增映射
        /// </summary>
        /// <param name="dbfieldID"></param>
        /// <param name="usfield"></param>
        /// <param name="dbid"></param>
        /// <returns></returns>
        private int addMapping(string dbfieldID, string usfield, string dbid)
        {
            int m = 0;
            bool result = false;
            SYS_CMS_US_FIELDMAP obj = new SYS_CMS_US_FIELDMAP();
            result = multiDbDao.IsExitstDbField(dbid, dbfieldID);
            if (!result)
            {
                result = multiDbDao.IsExitstUSField(dbid, usfield);
                if (!result)
                {
                    obj.DBID = int.Parse(dbid);
                    obj.FieldID = int.Parse(dbfieldID);
                    obj.USFieldID = int.Parse(usfield);
                    result = multiDbDao.AddFIELDMAP(obj);
                    if (result)
                    {
                        m = 1;
                    }
                }
                else
                {
                    m = 2;
                }
            }
            else
            {
                m = 3;
            }
            return m;

        }
        /// <summary>
        /// 修改映射
        /// </summary>
        /// <param name="dbfieldID"></param>
        /// <param name="usfield"></param>
        /// <param name="dbid"></param>
        /// <param name="sysid"></param>
        /// <returns></returns>
        private int updateMapping(string dbfieldID, string usfield, string dbid, string sysid)
        {
            int m = 0;
            bool result = false;
            SYS_CMS_US_FIELDMAP obj = new SYS_CMS_US_FIELDMAP();
            result = multiDbDao.IsExitstUSField(dbid, usfield, sysid);
            if (!result)
            {
                obj.DBID = int.Parse(dbid);
                obj.FieldID = int.Parse(dbfieldID);
                obj.USFieldID = int.Parse(usfield);
                obj.SysID = int.Parse(sysid);
                result = multiDbDao.UpdateFIELDMAP(obj);
                if (result)
                {
                    m = 1;
                }
            }
            else
            {
                m = 2;
            }

            return m;

        }
        /// <summary>
        /// 保存设置的跨库字段 FieldType：1=检索字段 2=排序字段 3=概览字段
        /// </summary>
        /// <returns></returns>
        public bool SavetUsField(IList<DBUSFIELD> fieldList, int filedtype)
        {
            //不管是更新还是新增都执行先删除后插入的规则
            bool result = false;
            try
            {
                Expression<Func<DBUSFIELD, bool>> query = c => (c.FieldType == filedtype);
                multiDbDao.DeleteUsField(query);
                foreach (DBUSFIELD item in fieldList)
                {
                    result = multiDbDao.SaveUsField(item);
                    if (!result)
                    {
                        LogOpr.Error("表SYS_CMS_DATABASE_PUBLISH_FIELD插入数据失败：FieldType:" + item.FieldType + "公共字段名称：" + item.RealFieldName);
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }
        /// <summary>
        /// 保存数据库相关信息
        /// </summary>
        /// <param name="dbobj"></param>
        /// <param name="list"></param>
        public bool DealDataBaseInfo(SYS_CMS_DATABASE dbobj, IList<SYS_CMS_DATABASE_FIELD> list, string fieldstr)
        {
            bool m = false;
            try
            {
                if (dbobj.SysID != 0)//修改
                {
                    m = multiDbDao.UpdateDB(dbobj);
                }
                else //新增
                {
                    m = multiDbDao.SaveDB(dbobj);
                }
                if (m)//主表操作成功后，处理数据库字段表
                {
                    foreach (SYS_CMS_DATABASE_FIELD item in list)
                    {
                        if (item.SysID != 0) //修改
                        {
                            multiDbDao.UpdateDBField(item);
                        }
                        else
                        {
                            multiDbDao.SaveDBField(item);
                        }
                    }
                    if (fieldstr != "") //删除记录
                    {
                        multiDbDao.DelDBField(fieldstr);
                        multiDbDao.DelDBFieldMap(fieldstr);
                    }

                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return m;
        }
        /// <summary>
        /// 删除数据库及字段
        /// </summary>
        /// <param name="id"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public bool DelDbAndFields(string id)
        {
            bool m = false;
            try
            {
                IList<SYS_CMS_DATABASE> list = userDBDAO.GetDBByID(id);
                 m = multiDbDao.DelDB(id);
                if (m)//删除数据库成功后，继续删除对应字段
                {
                    if (list != null)
                    {
                        foreach (SYS_CMS_DATABASE item in list)
                        {
                            multiDbDao.DelFieldByDBCode(item.DatabaseCode);
                        }

                    }
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return m;
        }

        /// <summary>
        /// 根据数据名称，和编码判断数据库是否存在
        /// </summary>
        /// <param name="name"></param>
        /// <param name="dbcode"></param>
        /// <param name="sysid">0代表新增时判断 反之代表修改</param>
        /// <returns></returns>
        public int IsExistDB(string name, string dbcode, int sysid)
        {
            int result = 0;
            try
            {
                IList<SYS_CMS_DATABASE> obj = singDbDao.GetDBList(null);
                IList<SYS_CMS_DATABASE> objdb;
                if (obj != null && obj.Count > 0)
                {
                    objdb = obj.Where(c => c.DatabaseName == name).ToList();
                    if (objdb != null && objdb.Count > 0)
                    {
                        if (sysid == 0)//新增
                        {
                            result = 1;//已存在数据库名
                            return result;
                        }
                        else  //修改
                        {
                            if (objdb[0].SysID != sysid)
                            {
                                result = 1;//已存在数据库名称
                                return result;
                            }
                        }
                    }
                    objdb = obj.Where(c => c.DatabaseCode == dbcode).ToList();
                    if (objdb != null && objdb.Count > 0)
                    {
                        if (sysid == 0)//新增
                        {
                            result = 2;//已存在数据库编码
                            return result;
                        }
                        else  //修改
                        {
                            if (objdb[0].SysID != sysid)
                            {
                                result = 2;//已存在数据库编码
                                return result;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogOpr.Error(ex.ToString());
            }
            return result;
        }

    }
}
